
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#ifndef _NGX_PALLOC_H_INCLUDED_
#define _NGX_PALLOC_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>


/*
 * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86.
 * On Windows NT it decreases a number of locked pages in a kernel.
 */
#define NGX_MAX_ALLOC_FROM_POOL (ngx_pagesize - 1)

#define NGX_DEFAULT_POOL_SIZE (16 * 1024)

#define NGX_POOL_ALIGNMENT 16
#define NGX_MIN_POOL_SIZE                                          \
    ngx_align((sizeof(ngx_pool_t) + 2 * sizeof(ngx_pool_large_t)), \
              NGX_POOL_ALIGNMENT)


typedef void (*ngx_pool_cleanup_pt)(void *data);

typedef struct ngx_pool_cleanup_s ngx_pool_cleanup_t;

struct ngx_pool_cleanup_s
{
    ngx_pool_cleanup_pt handler;
    void               *data;
    ngx_pool_cleanup_t *next;
};


typedef struct ngx_pool_large_s ngx_pool_large_t;

struct ngx_pool_large_s
{
    ngx_pool_large_t *next;
    void             *alloc;
#if (NGX_DEBUG_POOL)
    size_t size;
#endif
};


typedef struct
{
    u_char     *last;
    u_char     *end;
    ngx_pool_t *next;
    ngx_uint_t  failed;
} ngx_pool_data_t;


#if (NGX_DEBUG_POOL)

#define NGX_POOL_STATS_MAX 997 /* prime */

typedef struct ngx_pool_stat_s ngx_pool_stat_t;

struct ngx_pool_stat_s
{
    u_char          *func;
    size_t           size;
    size_t           num;  /* number of total pools */
    size_t           cnum; /* number of current used pools */
    size_t           lnum; /* number of calling ngx_palloc_large() */
    ngx_pool_stat_t *next;
};

extern ngx_pool_stat_t *ngx_pool_stats[NGX_POOL_STATS_MAX];
extern ngx_int_t        ngx_pool_stats_num;
#endif


struct ngx_pool_s
{
    ngx_pool_data_t     d;
    size_t              max;
    ngx_pool_t         *current;
    ngx_chain_t        *chain;
    ngx_pool_large_t   *large;
    ngx_pool_cleanup_t *cleanup;
    ngx_log_t          *log;
#if (NGX_DEBUG_POOL)
    size_t           size;
    ngx_pool_stat_t *stat;
#endif
};


typedef struct
{
    ngx_fd_t   fd;
    u_char    *name;
    ngx_log_t *log;
} ngx_pool_cleanup_file_t;

#if (T_DEPRECATED)
void *ngx_prealloc(ngx_pool_t *pool, void *p, size_t old_size, size_t new_size);
#endif

void *ngx_alloc(size_t size, ngx_log_t *log);
void *ngx_calloc(size_t size, ngx_log_t *log);

#if (NGX_DEBUG_POOL)
ngx_pool_t *__ngx_create_pool(size_t size, ngx_log_t *log, u_char *func,
                              ngx_int_t line);
#define ngx_create_pool(size, log) \
    __ngx_create_pool(size, log, (u_char *)__func__, __LINE__)
#else
ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log);
#endif

void ngx_destroy_pool(ngx_pool_t *pool);
void ngx_reset_pool(ngx_pool_t *pool);

void     *ngx_palloc(ngx_pool_t *pool, size_t size);
void     *ngx_pnalloc(ngx_pool_t *pool, size_t size);
void     *ngx_pcalloc(ngx_pool_t *pool, size_t size);
void     *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);


ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size);
void                ngx_pool_run_cleanup_file(ngx_pool_t *p, ngx_fd_t fd);
void                ngx_pool_cleanup_file(void *data);
void                ngx_pool_delete_file(void *data);


#endif /* _NGX_PALLOC_H_INCLUDED_ */
